#ifdef IMAM_LOG
#ifndef LOGSYS_FLAG
#define LOGSYS_FLAG
#endif
#endif

#include <project.h>
#define CITI_C

#include <sizes.h>
#include <aclconio.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>  
#include <acldev.h>
#include <aclstr.h>
#include <aclutil.h>
#include <prot8583.h>
#include <define.h>
#include <transact.h>
#include <dbmgr.h>
#include <mdlfuncs.h>
#include <svc.h>
#include <power.h> //imam

#include <entry.h>    //imam
#include <pinpad.h>   //imam
#include <protocol.h>
#include <packet.h>
#include <tran.h>
#include <comm.h>
#include <modem.h>
#include <ppt.h>
#include <piputl.h>
#include <pipmsg.h>
#include <isoutl.h>
#include <isoload.h>
#include <ifldtbl.h>
#include <msg.h>
#include <msgfuncs.h>
#include <bdt.h>
#include <hdt.h>
#include <trt.h>
#include <mht.h>
#include <iit.h>
#include <accum.h>
#include <form.h>
#include <date.h>
#include <mem.h>
#include <spdebug.h>
#include <funcids.h>
#include <pbatch.h>
#include <errno.h>
#include <ascii.h>
#include <amexhost.h>
#include <pct.h>
#include <formater.h>
#include <table.h>
#include <string.h>
#include <confio.h>
#include <aclfile.h>
#include <format.h>
#include <spamsg.h>
#include <oper.h>
#include <batmsg.h>
#include <ui.h>
#include <tct.h>
#include <multilng.h>
#include <logo.h>
#include <settlbat.h>
#include <msgclrk.h>
#include <msgshf.h>
#include <menufunc.h>
#include <mit.h>
#include <applidl.h>
#include <tblutil.h>
#include <menus.h>
#include <Validt.h>
#include <stats.h>
#include <cardmsg.h>
#include <card.h>
#include <msg.h>
#include <define.h>
#include <entry.h>
#include <pinpad.h>
#include <ctype.h>
#include <gds.h>
#include <power.h>
#include <tip.h>
#include <iso8583.h>
#include <beetle.h>
#include <xmodem.h>
#include <modemmsg.h>
#include <scdefine.h>
#include <rcptsegs.h>
#include <operate.h>
#include <cdt.h>///ivan
#include <battery.h>
#include <printer.h>
#include <rs232.h>
#include "IMAMids.h"
#include "IMAMsrc.h"
#include "UclCode.h"
#include "ImamUtil.h"
#include "ImamMenu.h"

#include "..\cpacsrc\cpacmsg.h"
#include "..\cpacsrc\cpacids.h"
#include "..\cpacsrc\cpacsrc.h"
#include "..\cpacsrc\cpac.h"
#include "..\cpacsrc\cpacsize.h"
#include "..\cpacsrc\cpacprnt.h"
#include "..\cpacsrc\cpacoper.h"

#include "..\CITIsrc\CITImsg.h"
#include "..\CITIsrc\CITIsrc.h"
#include "..\CITIsrc\CITIids.h"
#include "..\CITIsrc\CITIsize.h"

//#include "..\EPPSrc\EPPSrc.h"
//#include "..\CASHSrc\CASHSrc.h"
//#include "..\CABKSrc\CABKSrc.h"

#include "..\EMVSrc\EMVsrcdef.h"

#define IMAM_MAX_MENU_SIZE	256  //Maximal is 256
#define IMAM_MENU_L01		"MENU1"
#define IMAM_MENU_L02		"MENU2"

SMenu ImamMenu[IMAM_MAX_MENU_SIZE+1];
unsigned long lnImamMenuItem = 1L;
int NewTotalMenuCount = 0;  //assign by inRecountMenu();

int inImamUnlockKeyboard = 1;  // Add

extern VS_BOOL fDisplayLogoNow;
extern int inCurrentMenuIndex;
extern int inImamTerminalModel;
extern int inImamLineNumber;
extern int inImamMenuLine;

SMenu *ImamActiveMenu;

int inImamEnterKeyResponder() {
#ifdef IMAM_REMOVE_FUNC
ERR_BEEP();
	return(inEventResponder(KEY_CR));
#else
	
    int inTimerKeyPress;
    int inKeyPress;
	int inFunctionId = -1;
	char buff[10];
	char szOut[5];

    inTimerKeyPress = 5;
	memset(buff, 0x00, sizeof(buff));

    /** /pdebug(("--inEnterKeyResponder--"));*/
    if (inCurrentMenuIndex == ROOT_MENU_INDEX) {
		disable_hot_key();		//meca 20040823 -- to fix SPQALog0030
        clrscr();
		msg_select_file("F:englmsg.dat");
        vdDispMsgCentered(FUNCTIONS_TITLE_MSG, obDisp.inTitleLine, CLR_EOL);
		strcpy(szOut, "< __ >");
		write_at(szOut, 6, 6, 3);
		if (inImamUnlockKeyboard == 0){
			write_at("Press  -ALPHA-", 14, 2, 2);
			write_at("  To  Unlock  ", 14, 2, 3);
		} 
		memset(buff, 0x00, sizeof(buff));
		do {
			LOG_PRINTFF((0x08L, "before keypress buff = [%s]", buff));
			vdFlushKeyboardBuffer();
            inKeyPress = inWaitKey(inTimerKeyPress);
			LOG_PRINTFF((0x08L, "inKeyPress = [%d]", inKeyPress));
            switch (inKeyPress) {
            case KEY_CANCEL:
                enable_hot_key();
                return(inEventResponder(KEY_CANCEL)); // BJD: KEY_CLR -> KEY_CANCEL			
			case KEY_STR:
                enable_hot_key();
                return(inEventResponder(KEY_FUNC_STR));
			case KEY_ALP:
				{
					vdImamUnlockKeyboardAndDisplayOn(1);
					enable_hot_key();
					return(inEventResponder(KEY_CANCEL));
				}
			case KEY0:
            case KEY1:
            case KEY2:
            case KEY3:
            case KEY4:
            case KEY5:
            case KEY6:
            case KEY7:
            case KEY8:
            case KEY9:
				if (strlen(buff)<2){
					buff[strlen(buff)] = inKeyPress;
				}
				break;
			case KEY_CR:
				if(strlen(buff)>0) {
				    inFunctionId = atoi(buff);
					LOG_PRINTFF((0x08L, "FUNCTION = [%d]", inFunctionId));
				}				
				break;
			case KEY_BS:
				if(strlen(buff)>0) {
					buff[strlen(buff)-1] = 0x00; 
				}
				break;
            default:
                ERR_BEEP();
                break;
            }
			LOG_PRINTFF((0x08L, "buff = [%s]", buff));
			if (strlen(buff)==2) {
				strcpy(szOut, buff);
			} else if (strlen(buff)==1){
				szOut[0]=buff[0]; szOut[1]='_';
			} else {
				szOut[0]='_'; szOut[1]='_';
			}
			if (inImamUnlockKeyboard == 1){
				write_at(szOut, 2, 8, 3);
			}
			if (inFunctionId>=0){
				SVC_WAIT(500);
				break;
			}
		} while (TRUE);
		return inImamFunctionIDEventResponder(inFunctionId);
    } else {
        return(inEventResponder(KEY_CR));
	}
	#endif
}

int inImamActionIDEventResponder (int inActionCode)
{
	int inRetval = 0;
	int inImamAction = 0;
	int TotalMenuCount = NewTotalMenuCount;
	int found =0;
	int i = 0;

	for (i=0; i<TotalMenuCount; i++) {
		if (ImamMenu[i].inCode == inActionCode){
			lnImamMenuItem = ImamMenu[i].Number;
			found = 1;
			break;
		}
	}
	if (found==1) inImamAction = inImamProcessTrans(lnImamMenuItem);

	if (inImamAction==0){
		ERR_BEEP();
		enable_hot_key();
		inRetval = inEventResponder(KEY_CANCEL);
	} else {
		enable_hot_key();
		inRetval = inEventResponder(inImamAction);
	}
	vdImamDisplayMenu(0); //reset the menu
	return inRetval;
}

int inImamFunctionIDEventResponder (int inFuncCode)
{
	int inRetval = 0;
	int inImamAction = 0;
	int TotalMenuCount = NewTotalMenuCount;
	int found =0;
	int i = 0;
	
   
	for (i=0; i<TotalMenuCount; i++) {
		if (ImamMenu[i].inFunctionID == inFuncCode+1000){ //Add 1000 
			lnImamMenuItem = ImamMenu[i].Number;
			found = 1;
			break;
		}
	}
	if (found==1) inImamAction = inImamProcessTrans(lnImamMenuItem);

	if (inImamAction==0){
		ERR_BEEP();
		enable_hot_key();
		inRetval = inEventResponder(KEY_CANCEL);
	} else {
		enable_hot_key();
		inRetval = inEventResponder(inImamAction);
	}
	vdImamDisplayMenu(0); //reset the menu
	return inRetval;
}

int inImamCardResponder(void)
{
	return inImamActionIDEventResponder(IMAMM_SALE_EMV);
}

int inImamICC1Responder(void)
{
	return inImamActionIDEventResponder(IMAMM_SALE_EMV);
}

int inImamRecountMenu()
{
	int TotalMenuCount = sizeof(ImamMenu)/sizeof(SMenu)-1;
	int UnusedMenu = 0;
	char *CharMenu;
	char Buff[257];
	int i = 0;
	int inImamMainMenuCount = 0;
	int inMainMenuPos = 0;

	LOG_PRINTFF((0x08L, "Recounting Menu..."));
	LOG_PRINTFF((0x08L, "MAXIMUM TotalMenuCount Alowed= %d", TotalMenuCount));
	CharMenu = (char *)&ImamMenu;

	memset((void *)&ImamMenu, 0x00, sizeof(ImamMenu));
	{
		for (i=0; i<TotalMenuCount; i++) {  //Get Active/Inactive Information from config.sys
			if (inLoadMNURec(i) == VS_SUCCESS){
				ImamMenu[i].ActNumber = 1;
				ImamMenu[i].Direction = 0;
				ImamMenu[i].Number	 = 1;
				ImamMenu[i].inFunctionID		= inGetMNUMenuIndex();
				strcpy(ImamMenu[i].Name, szGetMNUMenuName()); 
				ImamMenu[i].inCode			= inGetMNUActionCode();
				ImamMenu[i].inBitmapID		= inGetMNUBitmapID();
				ImamMenu[i].inFooterID		= inGetMNUFooterID();
				ImamMenu[i].inDataID			= inGetMNUDataID();
				ImamMenu[i].inPasswordLevel	= inGetMNUPasswordLevel();
			} else {
				break;
			}
		}
	}
	LOG_PRINTFF((0x08L, "Total Original Menu Item = [%d]", i));

	memset(Buff, 0x00, sizeof(Buff));
	memset(Buff, '1', sizeof(Buff)-1);
	get_env(IMAM_MENU_L01, Buff, 128);
	get_env(IMAM_MENU_L02, &Buff[128], 128);
	vdTrimSpace(Buff);
	LOG_PRINTFF((0x08L, "MENU-%d=[%s]", strlen(Buff), Buff));
	for (i=0; i<TotalMenuCount; i++) {  //Get Active/Inactive Information from config.sys
		if (ImamMenu[i].Number>0) {
			ImamMenu[i].ActNumber = 1;
			if (Buff[i] == '0') ImamMenu[i].ActNumber = 0;
		}
		//LOG_PRINTFF((0x08L, "%03d, %d, %09ld [%s]", i, ImamMenu[i].ActNumber, ImamMenu[i].Number, ImamMenu[i].Name));
	}

	for (i=0; i<TotalMenuCount; i++) {  //Let Count the MainMenuCount first 
		if ((ImamMenu[i].ActNumber == 1) && (ImamMenu[i].Name[0] != '*')) {
			inImamMainMenuCount++;
			inMainMenuPos = i;
		}
	}
	if (inImamMainMenuCount==1){//if only one Main menu then suppress it, no need to display
		ImamMenu[inMainMenuPos].ActNumber = 0; //Disable the only main menu but its submenu remain active
		for (i=inMainMenuPos+1; i<TotalMenuCount; i++) {  
			if (ImamMenu[i].Name[0] == '*'){
				strcpy(ImamMenu[i].Name, &ImamMenu[i].Name[1]);
			} else {
				break;
			}
		}
	}

	LOG_PRINTFF((0x08L, "RECOUNTING NUMBER..."));
	for (i=0; i<TotalMenuCount; i++) {  //Renumbering, menu mark '*' ==> Number
	    if (i==0) {
			ImamMenu[i].Number = 1;
	    } else if (strlen(ImamMenu[i].Name) && strncmp(ImamMenu[i].Name, "*", 1)){  //a main menu
			if (ImamMenu[i-1].Number>=100000000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/100000000L+1);
			} else if (ImamMenu[i-1].Number>=1000000L)	{ ImamMenu[i].Number = (ImamMenu[i-1].Number/1000000L+1);
			} else if (ImamMenu[i-1].Number>=10000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/10000L+1);
			} else if (ImamMenu[i-1].Number>=100L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/100L+1);
			} else if (ImamMenu[i-1].Number>=1L)			{ ImamMenu[i].Number = (ImamMenu[i-1].Number/1L+1); }
	    } else if (strlen(ImamMenu[i].Name) && strncmp(ImamMenu[i].Name, "**", 2)){ //a submenu
			if (ImamMenu[i-1].Number>=100000000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/1000000L+1);
			} else if (ImamMenu[i-1].Number>=1000000L)	{ ImamMenu[i].Number = (ImamMenu[i-1].Number/10000L+1);
			} else if (ImamMenu[i-1].Number>=10000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/100L+1);
			} else if (ImamMenu[i-1].Number>=100L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/1L+1);
			} else if (ImamMenu[i-1].Number>=1L)			{ ImamMenu[i].Number = (ImamMenu[i-1].Number*100L+1); }
			strcpy(ImamMenu[i].Name, &ImamMenu[i].Name[1]);
	    } else if (strlen(ImamMenu[i].Name) && strncmp(ImamMenu[i].Name, "***", 3)){ //a sub sub menu
			if (ImamMenu[i-1].Number>=100000000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/10000L+1);
			} else if (ImamMenu[i-1].Number>=1000000L)	{ ImamMenu[i].Number = (ImamMenu[i-1].Number/100L+1);
			} else if (ImamMenu[i-1].Number>=10000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/1L+1);
			} else if (ImamMenu[i-1].Number>=100L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number*100L+1);}
			strcpy(ImamMenu[i].Name, &ImamMenu[i].Name[2]);
	    } else if (strlen(ImamMenu[i].Name) && strncmp(ImamMenu[i].Name, "****", 4)){
			if (ImamMenu[i-1].Number>=100000000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/100L+1);
			} else if (ImamMenu[i-1].Number>=1000000L)	{ ImamMenu[i].Number = (ImamMenu[i-1].Number/1L+1);
			} else if (ImamMenu[i-1].Number>=10000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number*100L+1);}
			strcpy(ImamMenu[i].Name, &ImamMenu[i].Name[3]);
	    } else if (strlen(ImamMenu[i].Name) && strncmp(ImamMenu[i].Name, "*****", 5)){
			if (ImamMenu[i-1].Number>=100000000L)		{ ImamMenu[i].Number = (ImamMenu[i-1].Number/1L+1);
			} else if (ImamMenu[i-1].Number>=1000000L)	{ ImamMenu[i].Number = (ImamMenu[i-1].Number*100L+1);}
			strcpy(ImamMenu[i].Name, &ImamMenu[i].Name[4]);
		} 
		//LOG_PRINTFF((0x08L, "%03d, %d, %09ld [%s]", i, ImamMenu[i].ActNumber, ImamMenu[i].Number, ImamMenu[i].Name));
	}
		
	LOG_PRINTFF((0x08L, "ADDING FIRST MENU & RECOUNT..."));
	for (i=0; i<TotalMenuCount; i++) {  //Renumbering as menu start from 1, need to make it 2
		if (ImamMenu[i].Number>=100000000L) ImamMenu[i].Number = (ImamMenu[i].Number/100000000L+1)*100000000L + ImamMenu[i].Number%100000000L;
		if (ImamMenu[i].Number>=1000000L) ImamMenu[i].Number = (ImamMenu[i].Number/1000000L+1)*1000000L + ImamMenu[i].Number%1000000L;
		if (ImamMenu[i].Number>=10000L) ImamMenu[i].Number = (ImamMenu[i].Number/10000L+1)*10000L + ImamMenu[i].Number%10000L;
		if (ImamMenu[i].Number>=100L) ImamMenu[i].Number = (ImamMenu[i].Number/100L+1)*100L + ImamMenu[i].Number%100L;
		if (ImamMenu[i].Number>=1L) ImamMenu[i].Number = (ImamMenu[i].Number/1L+1)*1L + ImamMenu[i].Number%1L;
		//LOG_PRINTFF((0x08L, "%03d, %d, %09ld [%s]", i, ImamMenu[i].ActNumber, ImamMenu[i].Number, ImamMenu[i].Name));
	}

	LOG_PRINTFF((0x08L, "INSERT MENU & RECOUNT..."));
	for (i=0; i<TotalMenuCount; i++) { //Insert **1, if there is **2
		if (ImamMenu[i].Number%100==2) {
			memmove(&CharMenu[(i+1)*sizeof(SMenu)], &CharMenu[(i)*sizeof(SMenu)], (TotalMenuCount-i-1)*sizeof(SMenu));
			if (i>0) {
				memcpy(&CharMenu[i*sizeof(SMenu)], &CharMenu[(i-1)*sizeof(SMenu)], sizeof(SMenu));
				ImamMenu[i].Number = ImamMenu[i].Number*100+1;
				ImamMenu[i].inCode = 0;
			} else {
				memset(&CharMenu[0], 0x00, sizeof(SMenu));
				ImamMenu[i].Number = 1;
				ImamMenu[i].inCode = 0;
				//strcpy(ImamMenu[i].Name, "Main");
				strcpy(ImamMenu[i].Name, "    ");
			}
			i++;
		}
	}
	//for (i=0; i<TotalMenuCount-1; i++) {  
	//	LOG_PRINTFF((0x08L, "%03d, %d, %09ld [%s]", i, ImamMenu[i].ActNumber, ImamMenu[i].Number, ImamMenu[i].Name));
	//}

	LOG_PRINTFF((0x08L, "TURN ON MENU HEADER and COUNT UNUSED MENU..."));
	for (i=0; i<TotalMenuCount; i++){  //All Menu Header will be turn On
		if (ImamMenu[i].Number%100==1) {
			ImamMenu[i].ActNumber = 1;
		}
		if (ImamMenu[i].Number==0) {  //	//Counting Unused Menu too
			UnusedMenu++;
		}
		//LOG_PRINTFF((0x08L, "%03d, %d, %09ld [%s]", i, ImamMenu[i].ActNumber, ImamMenu[i].Number, ImamMenu[i].Name));
	}
	TotalMenuCount -= UnusedMenu;
	NewTotalMenuCount = TotalMenuCount;
	LOG_PRINTFF((0x08L, "TotalMenuCount = [%d], UNUSED = [%d]", TotalMenuCount, UnusedMenu));
	LOG_PRINTFF((0x08L, "SORTING MENU..."));
	for (i=0; i<TotalMenuCount-1; i++) {  //Sorting Menu by Menu[i].Number
		if (ImamMenu[i].Number > ImamMenu[i+1].Number) {
			memcpy(&CharMenu[TotalMenuCount*sizeof(SMenu)], &CharMenu[i*sizeof(SMenu)], sizeof(SMenu));
			memcpy(&CharMenu[i*sizeof(SMenu)], &CharMenu[(i+1)*sizeof(SMenu)], sizeof(SMenu));
			memcpy(&CharMenu[(i+1)*sizeof(SMenu)], &CharMenu[TotalMenuCount*sizeof(SMenu)], sizeof(SMenu));
			i = -1;
		}
	}

	//for (i=0; i<TotalMenuCount-1; i++) {  
	//	LOG_PRINTFF((0x08L, "%03d, %d, %09ld [%s]", i, ImamMenu[i].ActNumber, ImamMenu[i].Number, ImamMenu[i].Name));
	//}

	for (i=0; i<TotalMenuCount; i++){
		if (ImamMenu[i].ActNumber == 0 && ImamMenu[i].Number > 0) {   //find in active menu 
			long DelNum = ImamMenu[i].Number;
			int j=0;
			for (j=i; j<TotalMenuCount; j++) { //delete inactive menu and it's submenu, rearange the Menu
				if (ImamMenu[j].Number==DelNum ||
					ImamMenu[j].Number/100==DelNum		|| ImamMenu[j].Number/10000==DelNum || 
					ImamMenu[j].Number/1000000L==DelNum	|| ImamMenu[j].Number/100000000L==DelNum) {
					//LOG_PRINTFF((0x08L, "Menu %ld [%ld.%s] Deleted", DelNum, ImamMenu[j].Number, ImamMenu[j].Name));
					memmove(&CharMenu[j*sizeof(SMenu)], &CharMenu[(j+1)*sizeof(SMenu)], (TotalMenuCount-j-1)*sizeof(SMenu));
					NewTotalMenuCount--;
					memset(&CharMenu[NewTotalMenuCount*sizeof(SMenu)], 0x00, sizeof(SMenu));
					j--;
				}
				if (j>=NewTotalMenuCount) break;
			}
			for (j=i; j<NewTotalMenuCount; j++) {  //Re Value the Menu Number
				if (ImamMenu[j].Number>DelNum && ImamMenu[j].Number<DelNum/100*100+100) { //(606/100*100+100 == 700)
					long ChangeNum = ImamMenu[j].Number;
					int k=0;
					ImamMenu[j].Number -= 1;
					for (k=j; k<NewTotalMenuCount; k++){  //Re value all sub menu
						if (ImamMenu[k].Number==ChangeNum) {
							ImamMenu[k].Number = ChangeNum;
						} else if (ImamMenu[k].Number/100==ChangeNum) {
							ImamMenu[k].Number = (ImamMenu[k].Number/100-1)*100 + ImamMenu[k].Number%100;
						} else if (ImamMenu[k].Number/10000==ChangeNum) {
							ImamMenu[k].Number = (ImamMenu[k].Number/10000-1)*10000L + ImamMenu[k].Number%10000;
						} else if (ImamMenu[k].Number/1000000L==ChangeNum) {
							ImamMenu[k].Number = (ImamMenu[k].Number/1000000L-1)*1000000L + ImamMenu[k].Number%1000000L;
						} else if (ImamMenu[k].Number/100000000L==ChangeNum) {
							ImamMenu[k].Number = (ImamMenu[k].Number/100000000L-1)*100000000L + ImamMenu[k].Number%100000000L;
						}
					}
				}
			}
			if (j>0) i--;
		}
	}
	for (i=NewTotalMenuCount-1; i>=0; i--) {  //Recalculate the menu direction
		if (ImamMenu[i].Number%100>=inImamMenuLine+1) {
			int J1 = i-ImamMenu[i].Number%100+1;
			int Ji;
			for (Ji=0; Ji<ImamMenu[i].Number%100; Ji++) {
				if (Ji<inImamMenuLine) {
					ImamMenu[J1+Ji].Direction = 2;
				} else if ((ImamMenu[i].Number%100-((Ji)/inImamMenuLine*inImamMenuLine))<=inImamMenuLine) {
					ImamMenu[J1+Ji].Direction = -2;
				} else {
					ImamMenu[J1+Ji].Direction = 1;
				}
			}
			i -= (ImamMenu[i].Number%100-1);
		} else {
			ImamMenu[i].Direction = 0;
		}
	}
	for (i=NewTotalMenuCount-1; i>=0; i--) {  //Rename custom menu
		if (!strcmp(ImamMenu[i].Name, "TRANSFER TO")) {
			if (ImamMenu[i].Number<10000) {
				strcpy(ImamMenu[i].Name, "TRANSFER");
			}
		}
	}

	LOG_PRINTFF((0x08L, "New TotalMenuCount = %d", NewTotalMenuCount));
	//for (i=0; i<NewTotalMenuCount; i++) {
	//	LOG_PRINTFF((0x08, "[%ld (%d)] %s", ImamMenu[i].Number, ImamMenu[i].Direction, ImamMenu[i].Name));
	//}
	ImamActiveMenu = &ImamMenu[0]; //Just init it so that IMAM_ECHO dll(FUNCTION ##), not crash
	return 1;
}


// MenuAction=0  ==> go to root menu;
// MenuAction=1  ==> go to next level menu and page=1;
// MenuAction=2  ==> back to previous level and same previous page;
// MenuAction=3  ==> move back/forward page
// MenuAction=4  ==> No Action
void vdImamDisplayMenu(int MenuAction)
{
	vdImamDisplayMenuComplete(MenuAction);
}

void vdImamDisplayMenuComplete(int MenuAction)
{
	int TotalMenuCount = NewTotalMenuCount;
	static unsigned long CurrentMenuPage = 1;   //01-99 for root menu, 01xx-99xx for sub meny, 01yyxx-99yyxx for dst				
	char MsgBuff[64];
	int found = 0;
	int i = 0;
	int MenuDirection = 0;
	char buff[128];

	int inImamMenuLine = 6;// imam 
	window(1,1, 21, inImamLineNumber);
	if (inImamTerminalModel == 670) {
		inImamMenuLine = 6;
	}else if (inImamTerminalModel == 810)
	{ inImamMenuLine = 4;
	}
	else {
		inImamMenuLine = 4;
	}
	LOG_PRINTFF((0x08L, "PREV lnImamMenuItem = [%ld]", lnImamMenuItem));
	if (MenuAction == 0) {
		CurrentMenuPage = 1;
	} else if (MenuAction == 1) {
		CurrentMenuPage = lnImamMenuItem*100 + 1;
	} else if (MenuAction == 2) {
		CurrentMenuPage = CurrentMenuPage/100;
	} else if (MenuAction == 3) {
		for (i=0; i<TotalMenuCount; i++) {
			if (ImamMenu[i].Number == CurrentMenuPage) break;
		}
		if (ImamMenu[i].Direction > 0) {
			CurrentMenuPage = CurrentMenuPage + inImamMenuLine;
			MenuDirection = 1;
		}
		if (ImamMenu[i].Direction < 0) {
			CurrentMenuPage = CurrentMenuPage - inImamMenuLine;
			MenuDirection = -1;
		}
	} else if (MenuAction == 4){
		//CurrentMenuPage=1;
	}
	//lnImamMenuItem = CurrentMenuPage = (((CurrentMenuPage-1)/inImamMenuLine) * inImamMenuLine) + 1;
	lnImamMenuItem = CurrentMenuPage = ((((CurrentMenuPage%100)-1)/inImamMenuLine) * inImamMenuLine) + 1 + (CurrentMenuPage/100*100);
	
	LOG_PRINTFF((0x08L, "CURR[0] lnImamMenuItem = [%ld]", lnImamMenuItem));
	found=-1;
	for (i=0; i<TotalMenuCount; i++) {
		if (ImamMenu[i].Number == CurrentMenuPage) {
			found = i;
		}
	}
	if (found==-1) {
		if (MenuAction==1) {
			CurrentMenuPage = CurrentMenuPage/100;
			//lnImamMenuItem = CurrentMenuPage = (CurrentMenuPage-1)/inImamMenuLine * inImamMenuLine + 1;
			lnImamMenuItem = CurrentMenuPage = ((((CurrentMenuPage%100)-1)/inImamMenuLine) * inImamMenuLine) + 1 + (CurrentMenuPage/100*100);
			for (i=0; i<TotalMenuCount; i++) {
				if (ImamMenu[i].Number == CurrentMenuPage) {
					found = i;
				}
			}
		} else {
			lnImamMenuItem = CurrentMenuPage=1;
			found=1;
		}
	}
	LOG_PRINTFF((0x08L, "CURR[1] lnImamMenuItem = [%ld]", lnImamMenuItem));
	for (i=found; (i<found+inImamMenuLine && i<TotalMenuCount); i++) {
		if (ImamMenu[i].Number >= CurrentMenuPage && ImamMenu[i].Number < CurrentMenuPage+99) {
			if ((MenuDirection) && (ImamMenu[i].Direction == 1 || ImamMenu[i].Direction == -1))
					ImamMenu[i].Direction = MenuDirection;
		}
	}

	for (i=0; i<inImamLineNumber/2; i++){
		write_at("                             ", 16, 1, i+1);
	}

	if (inImamMenuLine == 6) { 
		memset(buff, 0x00, sizeof(buff));
		get_font(buff);
		set_font(ASC8X21_VFT);
	}
	for (i=0; i<TotalMenuCount; i++) {
		if (ImamMenu[i].Number == CurrentMenuPage) {
			if (ImamMenu[i].Direction > 0)		MsgBuff[0] = 0x00; 
			else if (ImamMenu[i].Direction < 0) MsgBuff[0] = 0x01;
			else							MsgBuff[0] = 0x20;	
			if (inImamMenuLine == 6){
				write_at(MsgBuff,1,1, 16);
			} else {
			  if (inImamTerminalModel == 810)
			  	write_at(MsgBuff,1,1, inImamMenuLine*2);
			  else	
				write_at(MsgBuff,1,1, inImamMenuLine);
			}
			if (ImamMenu[i].Number % 100 == 1) {
				char buff2[128];
				memset(buff2, 0x00, sizeof(buff2));
				get_font(buff2);
				set_font(ASC4X16_VFT);
				//set_font("F:asc4x16i.vft");
				memset(MsgBuff, 0x00, sizeof(MsgBuff));
				strcpy(MsgBuff, ImamMenu[i].Name);
				if (strlen(MsgBuff)<16) strncat(MsgBuff, "                    ", 16-strlen(MsgBuff));
				write_at(MsgBuff, strlen(MsgBuff), 1, 1);
				//set_font("F:asc4x16.vft");
				set_font(buff2);
			} else {
				if (inImamMenuLine == 6){
					write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 22-strlen(ImamMenu[i].Name), 1);
				} else {
				          if (inImamTerminalModel == 810)
						 write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 17-strlen(ImamMenu[i].Name), 1);
				             else
						write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 17-strlen(ImamMenu[i].Name), 1);
				}
			}
		}
		if (ImamMenu[i].Number == CurrentMenuPage+1) {
			if (inImamMenuLine == 6){
				write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 22-strlen(ImamMenu[i].Name), 4);
			} else {
			 	 if (inImamTerminalModel == 810)
					write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 17-strlen(ImamMenu[i].Name), 3);
				else
					write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 17-strlen(ImamMenu[i].Name), 2);
			}
		}
		if (ImamMenu[i].Number == CurrentMenuPage+2){
			if (inImamMenuLine == 6){
				write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 22-strlen(ImamMenu[i].Name), 7);
			} else {
				 if (inImamTerminalModel == 810)
					write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 17-strlen(ImamMenu[i].Name), 5);
				else
				write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 17-strlen(ImamMenu[i].Name), 3);
			}
		}
		if (ImamMenu[i].Number == CurrentMenuPage+3){
			if (inImamMenuLine == 6){
				write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 22-strlen(ImamMenu[i].Name), 10);
			} else {
			 if (inImamTerminalModel == 810)
					write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 17-strlen(ImamMenu[i].Name), 7);
				else
				write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 17-strlen(ImamMenu[i].Name), 4);
			}
		}
		if (inImamMenuLine == 6) {
			if (ImamMenu[i].Number == CurrentMenuPage+4)
				write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 22-strlen(ImamMenu[i].Name), 13);		
			if (ImamMenu[i].Number == CurrentMenuPage+5)
				write_at(ImamMenu[i].Name, strlen(ImamMenu[i].Name), 22-strlen(ImamMenu[i].Name), 16);		
		}
	}
	if (inImamMenuLine == 6) { 
		set_font(buff);
	}
	//set_font("");
	LOG_PRINTFF((0x08L, "CURR[2] lnImamMenuItem = [%ld]", lnImamMenuItem));
}

int inImamProcessTrans(long CurrMenuIndex)
{
	if (inImamUnlockKeyboard == 0) return 0;
	return (inImamProcessTransComplete(CurrMenuIndex));
}

int inImamProcessTransComplete(long CurrMenuIndex)
{
#ifndef IMAM_BNI
	char buff[22];
#endif
	int i = 0;
	int found = 0;
	int TotalMenuCount = NewTotalMenuCount;
//	vdFlushCardBuffer();
	vdFlushKeyboardBuffer();

	for (i=0; i<inImamLineNumber/2; i++){
		write_at("                             ", 16, 1, i+1);
	}
	for (i=0; i<TotalMenuCount; i++) {
		if (ImamMenu[i].Number == CurrMenuIndex) {
			found = i;
			break;
		}
	}
	if (found){
		ImamActiveMenu = &ImamMenu[found];  //copy address so accessible from MiniAtm.c
	}

	if (found) {
		vdSetActionFont();
		vdImamDisplayTitle(ImamMenu[found].Name);
		if (inGetPwdFromUser(ImamMenu[found].inPasswordLevel, NO_PIT_INDEX) != VS_SUCCESS) {
			vdSetMenuFont();
			vdImamDisplayMenu(4);
			return 0;
		}
		vdSetMenuFont();
	}
	vdImamDisplayMenu(1); //Try Next Menu if Available
	if (found == 0) {
		return 0;
	} else {
		vdImamClearScreen();
		return ImamMenu[found].inCode;
	}	
}

int inImamSelectMenu(TRANSACTION_OBJECT *pobTran)
{
	//clrscr();
	//inShowTitle(pobTran);
	return inMenuSelection();
}

int inMenuSelection()
{
	int inCurrPage=0;
	char buff[257];
	char szCurrFont[20];
	char szDisplayBuff[30];
	int karakter=0;
	int index;
	int IndexMax, IndexAdj;
	int i;
	SMenu ImamOriginalMenu[200];
	int inTotalMenu = sizeof(ImamOriginalMenu)/sizeof(SMenu);
	memset((void *)&ImamOriginalMenu, 0x00, sizeof(ImamOriginalMenu));

	for (i=0; i<inTotalMenu; i++) {  //Get Active/Inactive Information from config.sys
		if (inLoadMNURec(i) == VS_SUCCESS){
			ImamOriginalMenu[i].ActNumber = 1;
			ImamOriginalMenu[i].Direction = 0;
			ImamOriginalMenu[i].Number	 = 1;
			ImamOriginalMenu[i].inFunctionID		= inGetMNUMenuIndex();
			strcpy(ImamOriginalMenu[i].Name, szGetMNUMenuName()); 
			ImamOriginalMenu[i].inCode			= inGetMNUActionCode();
			ImamOriginalMenu[i].inBitmapID		= inGetMNUBitmapID();
			ImamOriginalMenu[i].inFooterID		= inGetMNUFooterID();
			ImamOriginalMenu[i].inDataID			= inGetMNUDataID();
			ImamOriginalMenu[i].inPasswordLevel	= inGetMNUPasswordLevel();
		} else {
			break;
		}
	}
	inTotalMenu = i;

	memset(szCurrFont, 0x00, sizeof(szCurrFont));
	get_font(szCurrFont);

	memset(buff, 0x00, sizeof(buff));
	memset(buff, '1', sizeof(buff)-1);
	get_env(IMAM_MENU_L01, buff, 128);
	get_env(IMAM_MENU_L02, &buff[128], 128);
	vdTrimSpace(buff);

	if (inImamLineNumber==16){
		IndexMax=4;
		IndexAdj=1;
	} else {
		IndexMax=3;
		IndexAdj=0;
	}

	do {
		vdImamClearSevenLine();
		set_font(ASC8X21_VFT);
		write_at("\x20\x00\x20\x20\x20\x01", 6, 1, inImamLineNumber);
		for (index=0; index<IndexMax; index++) {
			if (inCurrPage+index<inTotalMenu) {
				memset(szDisplayBuff, 0x00, sizeof(szDisplayBuff));
				strncpy(szDisplayBuff, "........................", 21);
				strncpy(szDisplayBuff, ImamOriginalMenu[inCurrPage+index].Name, strlen(ImamOriginalMenu[inCurrPage+index].Name));
				if (buff[inCurrPage+index] == '0') {strcpy(&szDisplayBuff[18], "OFF");} else {strcpy(&szDisplayBuff[19], "ON");}
				if (inImamLineNumber==16){
					display_at(1, 4+(index*3), szDisplayBuff, NO_CLEAR);
				} else {
					display_at(1, 3+(index*2), szDisplayBuff, NO_CLEAR);
				}
			}
		}
		vdFlushKeyboardBuffer();
		karakter=0;
		do {
			SVC_WAIT(0);
			if (KBHIT()) karakter = get_char();
			if (karakter == 0x01) {		//F1
				if (IndexAdj){
					if (buff[inCurrPage] == '0') {buff[inCurrPage] = '1';} else {buff[inCurrPage] = '0';}
					break;
				}				
			} else if (karakter == 0x02) {		//F2
				if (buff[inCurrPage+IndexAdj] == '0') {buff[inCurrPage+IndexAdj] = '1';} else {buff[inCurrPage+IndexAdj] = '0';}
				break;
			} else if (karakter == 0x03) {		//F3
				if (buff[inCurrPage+IndexAdj+1] == '0') {buff[inCurrPage+IndexAdj+1] = '1';} else {buff[inCurrPage+IndexAdj+1] = '0';}
				break;
			} else if (karakter == 0x04) {		//F4
				if (buff[inCurrPage+IndexAdj+2] == '0') {buff[inCurrPage+IndexAdj+2] = '1';} else {buff[inCurrPage+IndexAdj+2] = '0';}
				break;
			} else if (karakter == 97) {		//key_a
				if (inCurrPage+IndexMax < inTotalMenu) inCurrPage += IndexMax;
				break;
			} else if (karakter == 98) {		//key_b
				if (inCurrPage-IndexMax >= 0) inCurrPage -= IndexMax;
				break;
			} else if (karakter == 99) {		//key_c
			} else if (karakter == 100) {		//key_d
			} else if (karakter == 0x1B) {		//esc, cancel change
				return 1;
			} else if (karakter == 13) {		//enter, execute change
				break;
			} else {
				karakter = 0;
			}
		} while (1);
		if (karakter==13) break;
	} while (1);
	vdImamClearSevenLine();
	DisplayStatus("PLEASE WAIT...");
	put_env(IMAM_MENU_L01, buff, 128);
	put_env(IMAM_MENU_L02, &buff[128], 128);
	set_font(szCurrFont);
	inImamRecountMenu();
	vdImamDisplayMenu(0);
	return 1;
}

void vdImamDisplayTitle(char *msg)
{
	char buff[30];
	int inMsgLen = strlen(msg);

	if (inMsgLen>21) inMsgLen = 21;

	memset(buff, 0x00, sizeof(buff));
	memset(buff, 0x20, 21);
	strncpy(buff, msg, inMsgLen);
	//strncpy(&buff[(21-strlen(msg))/2], msg, inMsgLen);
	//set_font("F:asc8x21i.vft");
	write_at(buff, strlen(buff), 1, 1);
	//set_font("");
}

void vdImamClearSevenLine(void) 
{
	int i;
	set_font(ASC8X21_VFT);
	for (i=0; i<inImamLineNumber-1; i++) {
		gotoxy(1, 2);
		delline();
	}
}

void vdImamUnlockKeyboardAndDisplayOn(int Mode)
{
  	vdSetMenuFont();
	fDisplayLogoNow = VS_TRUE;
	vdSelectMenu(ROOT_MENU_ID);
	set_backlight(Mode);
	inImamUnlockKeyboard = Mode;
}

void vdImamClearScreen(void)
{
	int i;
	char buff[20];
	memset(buff, 0x00, sizeof(buff));
	get_font(buff);
	set_font(ASC4X16_VFT);
	for (i=0; i<inImamLineNumber/2; i++){
		write_at("                             ", 16, 1, i+1);
	}
	set_font(buff);
}
